package com.lost.octopus.es.helper.entity.wrapper;

import com.lost.octopus.es.helper.constant.EsMatchType;
import com.lost.octopus.es.helper.entity.model.FieldConfig;
import com.lost.octopus.es.helper.util.StringUtil;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.ExistsQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 检索某个字段为空（null or ""）或者非空 （不为null or 不为""）
 * 默认 -1或1查询为空，0查询非空
 * <br/>
 * 注解：{@code @EsSearch(fieldName = "csrq", queryType = EsQueryBlankWrapper.class)}
 * <br/>
 * 示例：{@code "-1"}
 * <br/>
 * 效果：{@code
 * <br/>
 * 非空
 * <p>非字符串{"bool":{"must_not":[{"exists":{"field":"csrq"}}]}} </p>
 * <p>字符串{"bool":{"should":[{"match":{"csrq":{"query":""}}},{"bool":{"must_not":[{"exists":{"field":"csrq"}}]}}]}}</p>
 * 为空
 * <p>非字符串{"bool":{"must":[{"exists":{"field":"csrq"}}]}} </p>
 * <p>字符串{"bool":{"must":[{"match":{"csrq":{"query":""}}},{"exists":{"field":"csrq"}}]}}</p>
 * }
 * @author zhangbh
 **/
@Component
public class EsQueryBlankWrapper extends AbstractQueryWrapper {

    /**
     * 默认：
     * searchVal当value等于-1时启用查询
     * fieldName查询时，指定自定义字段
     */
    static final String DEFAULT_OTHER_PARAM = "-1";
    static final String NOT_BLANK_SEARCH_KEY = "0";

    @Override
    public QueryBuilder addWrapper(BoolQueryBuilder builder, FieldConfig field) {
        String fieldName = field.getName();
        Object value = field.getValue();

        // 如果为空返回
        if (StringUtil.isBlank(value)) {
            return null;
        }
        // 是否搜索空
        boolean searchBlank = !NOT_BLANK_SEARCH_KEY.equals(value.toString());

        // 如果不是text 或者keyword类型，就不能进行term查询 直接返回
        if (!field.isStringType()) {
            ExistsQueryBuilder existsQuery = QueryBuilders.existsQuery(fieldName);
            // 给外部使用，需要重新套一下返回
            BoolQueryBuilder result = QueryBuilders.boolQuery();
            if (searchBlank) {
                builder.mustNot(existsQuery);
                result.mustNot(existsQuery);
            } else {
                builder.must(existsQuery);
                result.must(existsQuery);
            }
            return result;
        }
        FieldConfig config = FieldConfig.empty().setMatchType(EsMatchType.term).setValue("").setName(fieldName);
        if (searchBlank) {
            BoolQueryBuilder shouldBuilder = QueryBuilders.boolQuery();
            // 查询不存在
            BoolQueryBuilder existQuery = QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(fieldName));
            // 为空或者不存在
            shouldBuilder.should(useBuilder(config));
            shouldBuilder.should(existQuery);
            builder.must(shouldBuilder);
            return shouldBuilder;
        } else {
            // 存在且不为空字符串
            ExistsQueryBuilder existsQuery = QueryBuilders.existsQuery(fieldName);
            QueryBuilder notBlank = useBuilder(config);
            builder.must(existsQuery).mustNot(notBlank);
            // 提供外部调用的对象
            BoolQueryBuilder mustAll = QueryBuilders.boolQuery();
            mustAll.must(existsQuery).mustNot(notBlank);
            return mustAll;
        }

    }
}
